#include "uart_device.h"
#include "usart.h"
#include "my_errno.h"
#include <string.h>

#define UART_RX_QUEUE_LEN	10

static UARTDevice g_tUART1;





void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	PUARTData ptPrivData;

	if (huart == &huart1)
	{
		ptPrivData = g_tUART1.privData;
		xSemaphoreGiveFromISR(ptPrivData->xSemaphoreTx, NULL); //释放信号量
	}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	PUARTData ptPrivData;
	int len = huart->RxXferSize - huart->RxXferCount;

	if (huart == &huart1)
	{
		ptPrivData = g_tUART1.privData;
		
		/* 写队列 */
		for (int i = 0; i < len; i++)
		{
			xQueueSendFromISR(ptPrivData->xQueueRx, &ptPrivData->rxDatas[i], NULL);
		}
		/* 再次开启数据的接收 */
		HAL_UARTEx_ReceiveToIdle_DMA(ptPrivData->handle, ptPrivData->rxDatas, huart->RxXferSize);
	}
}

//---------------------------------------------  DMA+IDLE 、FreeRTOS队列+信号量
static int UARTInit(struct UART_Device *ptDev)
{
	if (NULL == ptDev)
		return -EINVAL;

	PUARTData ptPrivData = ptDev->privData;
	ptPrivData->xSemaphoreTx = xSemaphoreCreateBinary();
	ptPrivData->xQueueRx = xQueueCreate(UART_RX_QUEUE_LEN, 1);

	/* 启动 DMA+空闲中断 */
	HAL_UARTEx_ReceiveToIdle_DMA(ptPrivData->handle, ptPrivData->rxDatas, 100);

	return ESUCCESS;
}
static int UARTSend(struct UART_Device *ptDev, unsigned char *buf, int len, int timeoutMS)
{	
	if (NULL == ptDev)
		return -EINVAL;

	PUARTData ptPrivData = ptDev->privData;
	
	/* 仅仅使能 DMA 中断 */
	HAL_UART_Transmit_DMA(ptPrivData->handle, buf, len);
	
	/* 等待发送完毕：等待信号量 */
	if (pdTRUE == xSemaphoreTake(ptPrivData->xSemaphoreTx, timeoutMS))
		return ESUCCESS;
	else
		return -ETIMEDOUT;
	
}
static int UARTRecv(struct UART_Device *ptDev, unsigned char *data, int timeoutMS)
{
	if (NULL == ptDev)
		return -EINVAL;

	PUARTData ptPrivData = ptDev->privData;

	/* 读取队列得到数据，谁写队列？中断写队列 */
	if (pdTRUE == xQueueReceive(ptPrivData->xQueueRx, data, timeoutMS))
		return ESUCCESS;
	else
		return -ETIMEDOUT;
}

//------------------------------------------------
static UARTData g_tUART1Data = { &huart1 };
static UARTDevice g_tUART1 = {
	"usart1",
	UARTInit,
	UARTSend,
	UARTRecv,
	&g_tUART1Data
};

static PUARTDevice g_ptUARTDevices[] = {
	&g_tUART1
};

PUARTDevice GetUARTDevice(char *name)
{
	for (int i = 0; i < sizeof(g_ptUARTDevices)/sizeof(g_ptUARTDevices[0]); i++)
	{
		if (!strcmp(g_ptUARTDevices[i]->name, name))
			return g_ptUARTDevices[i];
	}

	return NULL;
}


